package besta.moon.engine;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import besta.moon.engine.table.Column;
import besta.moon.engine.table.Columns;
import besta.moon.sql.Expression;
import besta.moon.sql.MoonParser;
import besta.moon.sql.expression.ColumnExpression;
import besta.moon.sql.expression.ExpressionName;
import besta.moon.MoonException;
import besta.moon.MoonConnection;
import besta.moon.MoonCode;
import besta.moon.command.CommandSelect;
import besta.moon.engine.store.MoonImpl;
import besta.moon.engine.store.MoonPage;
import besta.moon.sql.expression.Expressions;
import besta.moon.sql.parser.SQLTokenizer;
import besta.moon.util.MoonUtils;

public class ViewTable extends View {

    final String sql;
    public final CommandSelect commandSelect;

    public ViewTable(MoonConnection con, String name, FileChannel raFile, long offset) throws Exception {
        super(name, new Columns());
        MoonPage storePage = new MoonPage(null, -1, raFile, offset);
        MoonImpl store = MoonImpl.createStore(null, storePage, SQLTokenizer.SELECT, offset);
        sql = store.readString();
        int type;
        while ((type = store.readInt()) != 0) {
            int offsetInPage = store.getCurrentOffsetInPage();
            int size = store.readInt();
            switch (type) {

            }
            store.setCurrentOffsetInPage(offsetInPage + size);
        }

        raFile.close();
        commandSelect = (CommandSelect) new MoonParser().parse(con, sql);
        createColumns(con);
    }

    public ViewTable(Database database, MoonConnection con, String name, String sql) throws Exception {
        super(name, new Columns());
        this.sql = sql;
        this.commandSelect = null;
        write(database, con);
    }

    public ViewTable(MoonConnection con, CommandSelect commandSelect) throws Exception {
        super("UNION", new Columns());
        this.sql = null;
        this.commandSelect = commandSelect;
        createColumns(con);
    }

    private void createColumns(MoonConnection con) throws Exception {
        commandSelect.compile(con);
        Expressions exprs = commandSelect.columnExpressions;
        for (int c = 0; c < exprs.size(); c++) {
            Expression expr = exprs.get(c);
            if (expr instanceof ExpressionName) {
                Column column = ((ExpressionName) expr).getColumn().copy();
                column.setName(expr.getAlias());
                columns.add(column);
            } else {
                columns.add(new ColumnExpression(expr));
            }
        }
    }

    public static void drop(Database database, String name) throws Exception {
        File file = new File(MoonUtils.createTableViewFileName(database, name));
        boolean ok = file.delete();
        if (!ok) {
            throw MoonException.create(MoonCode.VIEW_CANTDROP, name);
        }
    }

    private void write(Database database, MoonConnection con) throws Exception {
        FileChannel raFile = createFile(con, database);
        MoonPage storePage = new MoonPage(null, -1, raFile, 8);
        MoonImpl store = MoonImpl.createStore(null, storePage, SQLTokenizer.CREATE, 8);
        store.writeString(sql);
        store.writeInt(0); 

        store.writeFinsh(null);
        raFile.close();
    }

    @Override
    public void writeMagic(FileChannel raFile) throws Exception {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putInt(MAGIC_VIEW);
        buffer.putInt(TABLE_VIEW_VERSION);
        buffer.position(0);
        raFile.write(buffer);
    }

}
